package com.zx.notification.admin.service.impl;

import com.zx.core.enums.StatusEnum;
import com.zx.core.page.PageInfo;
import com.zx.core.wrapper.ObjectWrapper;
import com.zx.core.wrapper.PageWrapper;
import com.zx.core.wrapper.ResponseWrapper;
import com.zx.notification.admin.service.INotificationChannelsConfigService;
import com.zx.notification.common.dao.NotificationChannelsConfigMapper;
import com.zx.notification.common.enums.ChannelTypeEnum;
import com.zx.notification.common.enums.MqTypeEnum;
import com.zx.notification.common.mapstruct.NotificationChannelsConfigMapStructMapper;
import com.zx.notification.common.model.NotificationChannelsConfig;
import com.zx.notification.common.param.NotificationChannelsConfigParam;
import com.zx.notification.common.service.ConfigChangeListener;
import com.zx.notification.common.utils.NotificationNoUtils;
import com.zx.notification.common.vo.NotificationChannelsConfigVO;
import com.zx.security.block.uitls.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * description: 通知渠道配置管理服务实现类 <br>
 * create: 2025-10-17
 * </p>
 *
 * @author zhou  xun
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NotificationChannelsConfigServiceImpl implements INotificationChannelsConfigService {

    private final NotificationChannelsConfigMapper notificationChannelsConfigMapper;
    private final ConfigChangeListener configChangeListener;
    private final NotificationChannelsConfigMapStructMapper notificationChannelsConfigMapStructMapper;

    @Override
    public PageWrapper<NotificationChannelsConfigVO> getNotificationChannelsConfigVOListByPage(NotificationChannelsConfigParam notificationChannelsConfigParam) {
        PageWrapper<NotificationChannelsConfigVO> result = new PageWrapper<>();
        try {
            PageInfo pageInfo = new PageInfo(notificationChannelsConfigParam.getPageNum(), notificationChannelsConfigParam.getPageSize());
            notificationChannelsConfigParam.setPageNum(pageInfo.getPageNum());
            notificationChannelsConfigParam.setPageSize(pageInfo.getPageSize());

            // 查询总数
            Long count = notificationChannelsConfigMapper.getNotificationChannelsConfigListCount(notificationChannelsConfigParam.getChannelType(),
                    notificationChannelsConfigParam.getChannelName(),
                    notificationChannelsConfigParam.getMqType(),
                    notificationChannelsConfigParam.getStatus(),
                    notificationChannelsConfigParam.getCreateTimeStart(),
                    notificationChannelsConfigParam.getCreateTimeEnd()
            );
            if (count > 0) {
                // 分页查询列表
                List<NotificationChannelsConfig> notificationChannelsConfigList = notificationChannelsConfigMapper.getNotificationChannelsConfigListByPage(notificationChannelsConfigParam.getChannelType(),
                        notificationChannelsConfigParam.getChannelName(),
                        notificationChannelsConfigParam.getMqType(),
                        notificationChannelsConfigParam.getStatus(),
                        notificationChannelsConfigParam.getCreateTimeStart(),
                        notificationChannelsConfigParam.getCreateTimeEnd(),
                        notificationChannelsConfigParam.getPageNum(),
                        notificationChannelsConfigParam.getPageSize());
                List<NotificationChannelsConfigVO> list = notificationChannelsConfigList.stream()
                        .map(notificationChannelsConfigMapStructMapper::notificationChannelsConfigToNotificationChannelsConfigVO)
                        .toList();

                // 设置返回结果
                result.setData(list);
            }
            result.setTotal(count);
            result.setCurrentPageNum(notificationChannelsConfigParam.getPageNum());
            result.setTotalPage(pageInfo);
        } catch (Exception e) {
            log.error("获取通知渠道配置列表时发生错误", e);
            result.fail("获取通知渠道配置列表失败，请稍后重试");
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseWrapper addNotificationChannelsConfig(NotificationChannelsConfigParam notificationChannelsConfigParam) {
        ResponseWrapper result = new ResponseWrapper();

        try {
            // 验证参数
            ResponseWrapper validateResult = validateNotificationChannelsConfigParams(notificationChannelsConfigParam, true);
            if (validateResult.verifyFail()) {
                return validateResult;
            }

            // 验证渠道类型唯一性
            NotificationChannelsConfig existingConfig = notificationChannelsConfigMapper.selectByChannelType(notificationChannelsConfigParam.getChannelType());
            if (existingConfig != null) {
                result.fail("渠道类型已存在");
                return result;
            }

            // 创建通知渠道配置对象
            NotificationChannelsConfig notificationChannelsConfig = notificationChannelsConfigMapStructMapper.notificationChannelsConfigParamToNotificationChannelsConfig(notificationChannelsConfigParam);
            notificationChannelsConfig.setId(NotificationNoUtils.generateNotificationId());

            // 设置创建信息
            notificationChannelsConfig.setCreateBy(SecurityUtils.getUserId());
            notificationChannelsConfig.setCreateTime(LocalDateTime.now());

            // 插入通知渠道配置到数据库
            notificationChannelsConfigMapper.insertSelective(notificationChannelsConfig);

            // 发布渠道配置变更事件，触发缓存清理
            configChangeListener.publishConfigChange("mq_config", "channel_type:" + notificationChannelsConfig.getChannelType());
        } catch (Exception e) {
            log.error("添加通知渠道配置时发生错误", e);
            result.fail("添加通知渠道配置失败: " + e.getMessage());
            throw e; // 重新抛出异常以触发事务回滚
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseWrapper editNotificationChannelsConfig(NotificationChannelsConfigParam notificationChannelsConfigParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证参数
            ResponseWrapper validateResult = validateNotificationChannelsConfigParams(notificationChannelsConfigParam, false);
            if (validateResult.verifyFail()) {
                return validateResult;
            }

            // 验证通知渠道配置是否存在
            NotificationChannelsConfig existingNotificationChannelsConfig = notificationChannelsConfigMapper.selectByPrimaryKey(notificationChannelsConfigParam.getId());
            if (null == existingNotificationChannelsConfig) {
                result.fail("通知渠道配置不存在");
                return result;
            }

            // 验证渠道类型唯一性（如果类型有变更）
            if (!existingNotificationChannelsConfig.getChannelType().equals(notificationChannelsConfigParam.getChannelType())) {
                NotificationChannelsConfig configWithSameType = notificationChannelsConfigMapper.selectByChannelType(notificationChannelsConfigParam.getChannelType());
                if (configWithSameType != null) {
                    result.fail("渠道类型已存在");
                    return result;
                }
            }

            // 更新通知渠道配置信息
            NotificationChannelsConfig notificationChannelsConfigToUpdate = notificationChannelsConfigMapStructMapper.notificationChannelsConfigParamToNotificationChannelsConfig(notificationChannelsConfigParam);
            notificationChannelsConfigToUpdate.setUpdateBy(SecurityUtils.getUserId());
            notificationChannelsConfigToUpdate.setUpdateTime(LocalDateTime.now());
            notificationChannelsConfigMapper.updateByPrimaryKeySelective(notificationChannelsConfigToUpdate);

            // 发布渠道配置变更事件，触发缓存清理
            configChangeListener.publishConfigChange("mq_config", "channel_type:" + existingNotificationChannelsConfig.getChannelType());
        } catch (Exception e) {
            log.error("编辑通知渠道配置时发生错误", e);
            result.fail("编辑通知渠道配置失败: " + e.getMessage());
            throw e; // 重新抛出异常以触发事务回滚
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseWrapper deleteNotificationChannelsConfig(String notificationChannelsConfigId) {
        ResponseWrapper result = new ResponseWrapper();

        try {
            // 验证通知渠道配置是否存在
            NotificationChannelsConfig existingNotificationChannelsConfig = notificationChannelsConfigMapper.selectByPrimaryKey(notificationChannelsConfigId);
            if (null == existingNotificationChannelsConfig) {
                result.fail("通知渠道配置不存在");
                return result;
            }

            // 删除通知渠道配置
            notificationChannelsConfigMapper.deleteByPrimaryKey(notificationChannelsConfigId);

            // 发布渠道配置变更事件，触发缓存清理
            configChangeListener.publishConfigChange("mq_config", "channel_type:" + existingNotificationChannelsConfig.getChannelType());
        } catch (Exception e) {
            log.error("删除通知渠道配置时发生系统错误", e);
            result.fail("删除通知渠道配置失败: " + e.getMessage());
            throw e; // 重新抛出异常以触发事务回滚
        }

        return result;
    }

    @Override
    public ObjectWrapper<NotificationChannelsConfigVO> selectNotificationChannelsConfigById(String notificationChannelsConfigId) {
        ObjectWrapper<NotificationChannelsConfigVO> result = new ObjectWrapper<>();
        try {
            // 验证通知渠道配置是否存在
            NotificationChannelsConfig selectByPrimaryKey = notificationChannelsConfigMapper.selectByPrimaryKey(notificationChannelsConfigId);
            if (null == selectByPrimaryKey) {
                result.fail("通知渠道配置不存在");
                return result;
            }

            NotificationChannelsConfigVO notificationChannelsConfigVO = notificationChannelsConfigMapStructMapper.notificationChannelsConfigToNotificationChannelsConfigVO(selectByPrimaryKey);
            result.setData(notificationChannelsConfigVO);
        } catch (Exception e) {
            log.error("获取通知渠道配置信息时发生错误", e);
            result.fail("获取通知渠道配置信息失败，请稍后重试");
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseWrapper updateNotificationChannelsConfigStatus(NotificationChannelsConfigParam notificationChannelsConfigParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证通知渠道配置是否存在
            NotificationChannelsConfig existingNotificationChannelsConfig = notificationChannelsConfigMapper.selectByPrimaryKey(notificationChannelsConfigParam.getId());
            if (null == existingNotificationChannelsConfig) {
                result.fail("通知渠道配置不存在");
                return result;
            }

            // 更新通知渠道配置状态
            NotificationChannelsConfig notificationChannelsConfigToUpdate = new NotificationChannelsConfig();
            notificationChannelsConfigToUpdate.setId(notificationChannelsConfigParam.getId());
            notificationChannelsConfigToUpdate.setStatus(notificationChannelsConfigParam.getStatus());
            notificationChannelsConfigToUpdate.setUpdateBy(SecurityUtils.getUserId());
            notificationChannelsConfigToUpdate.setUpdateTime(LocalDateTime.now());
            notificationChannelsConfigMapper.updateByPrimaryKeySelective(notificationChannelsConfigToUpdate);

            // 发布渠道配置变更事件，触发缓存清理
            NotificationChannelsConfig channelConfig = notificationChannelsConfigMapper.selectByPrimaryKey(notificationChannelsConfigParam.getId());
            if (channelConfig != null) {
                configChangeListener.publishConfigChange("mq_config", "channel_type:" + channelConfig.getChannelType());
            }
        } catch (Exception e) {
            log.error("更新通知渠道配置状态时发生错误", e);
            result.fail("更新通知渠道配置状态失败: " + e.getMessage());
            // 重新抛出异常以触发事务回滚
            throw e;
        }

        return result;
    }

    /**
     * 验证通知渠道配置参数
     *
     * @param notificationChannelsConfigParam 通知渠道配置参数
     * @param isAdd                           是否为新增操作
     * @return 验证结果
     */
    private ResponseWrapper validateNotificationChannelsConfigParams(NotificationChannelsConfigParam notificationChannelsConfigParam, boolean isAdd) {
        ResponseWrapper result = new ResponseWrapper();

        // 新增时校验必填字段
        if (isAdd) {
            if (null == notificationChannelsConfigParam.getChannelType() || notificationChannelsConfigParam.getChannelType().isEmpty()) {
                result.fail("渠道类型不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getChannelName() || notificationChannelsConfigParam.getChannelName().isEmpty()) {
                result.fail("渠道名称不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getMqType() || notificationChannelsConfigParam.getMqType().isEmpty()) {
                result.fail("MQ类型不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getQueueName() || notificationChannelsConfigParam.getQueueName().isEmpty()) {
                result.fail("队列名称不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getQueueDestinationType() || notificationChannelsConfigParam.getQueueDestinationType().isEmpty()) {
                result.fail("队列目标类型不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getTopicName() || notificationChannelsConfigParam.getTopicName().isEmpty()) {
                result.fail("主题名称不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getTopicDestinationType() || notificationChannelsConfigParam.getTopicDestinationType().isEmpty()) {
                result.fail("主题目标类型不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getPushStrategy() || notificationChannelsConfigParam.getPushStrategy().isEmpty()) {
                result.fail("推送策略不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getMaxRetryCount()) {
                result.fail("最大重试次数不能为空");
                return result;
            }

            if (null == notificationChannelsConfigParam.getStatus()) {
                result.fail("状态不能为空");
                return result;
            }
        }

        // 校验渠道类型
        if (null != notificationChannelsConfigParam.getChannelType() && ChannelTypeEnum.getEnumByCode(notificationChannelsConfigParam.getChannelType()) == null) {
            result.fail("渠道类型不正确");
            return result;
        }

        // 校验MQ类型
        if (null != notificationChannelsConfigParam.getMqType() && MqTypeEnum.getEnumByCode(notificationChannelsConfigParam.getMqType()) == null) {
            result.fail("MQ类型不正确");
            return result;
        }

        // 校验队列目标类型
        if (null != notificationChannelsConfigParam.getQueueDestinationType() && !"QUEUE".equals(notificationChannelsConfigParam.getQueueDestinationType()) && !"TOPIC".equals(notificationChannelsConfigParam.getQueueDestinationType())) {
            result.fail("队列目标类型不正确");
            return result;
        }

        // 校验主题目标类型
        if (null != notificationChannelsConfigParam.getTopicDestinationType() && !"QUEUE".equals(notificationChannelsConfigParam.getTopicDestinationType()) && !"TOPIC".equals(notificationChannelsConfigParam.getTopicDestinationType())) {
            result.fail("主题目标类型不正确");
            return result;
        }

        // 校验推送策略
        if (null != notificationChannelsConfigParam.getPushStrategy() && !"REQUIRED".equals(notificationChannelsConfigParam.getPushStrategy()) && !"OPTIONAL".equals(notificationChannelsConfigParam.getPushStrategy()) && !"FALLBACK".equals(notificationChannelsConfigParam.getPushStrategy())) {
            result.fail("推送策略不正确");
            return result;
        }

        // 校验状态
        if (null != notificationChannelsConfigParam.getStatus() && StatusEnum.getEnumByCode(notificationChannelsConfigParam.getStatus()) == null) {
            result.fail("状态不正确");
            return result;
        }

        return result;
    }
}